package indv.cfeng.util;

import indv.cfeng.function.FuncWithOneArg;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Cfeng
 * rule: 对象类型参数都需要判断有效性
 */

public final class ListUtility {

    private ListUtility() {
        throw new IllegalStateException("static class");
    }

    /**
     * 判断集合是否为空
     */
    public static <T> boolean isNullOrEmpty(List<T> list) {
        return !any(list);
    }

    /**
     * 判断集合是否非空
     */
    public static <T> boolean any(List<T> list) {
        return list != null && !list.isEmpty();
    }

    /**
     * 按照 item断言predicate, 任何一个成功则成功
     */
    public static <T> boolean any(List<T> source, FuncWithOneArg<T, Boolean> predicate) {
        if (source == null) {
            throw new IllegalArgumentException("source");
        }
        //断言流程
        if (predicate == null) {
            throw new IllegalArgumentException("predicate");
        }

        for (T item : source) {
            if (predicate.execute(item)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 合并多个集合
     */
    @SafeVarargs //该注解可消除编译器的可变参数泛型执行警告
    public static <T> List<T> join(List<? extends T>... args) {
        if (args == null || args.length == 0) {
            return null;
        }

        return Stream.of(args)
                .filter(ListUtility::any)
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
    }

    /**
     * 将元素分割成size大小的子集合列表
     */
    public static <T> List<List<T>> partition(List<T> list, int size) {
        if (ListUtility.isNullOrEmpty(list)) {
            throw new IllegalArgumentException("list");
        }
        if (size <= 0) {
            throw new IllegalArgumentException("size");
        }
        List<List<T>> result = new ArrayList<>();
        for (int i = 0; i < list.size(); i += size) {
            result.add(ListUtility.take(list, i, size));
        }
        return result;
    }

    /**
     * 取集合中跳过前skipCount个元素后的takeCount个元素
     */
    public static <T> List<T> take(List<T> source, int skipCount, int takeCount) {
        if (ListUtility.isNullOrEmpty(source)) {
            throw new IllegalArgumentException("source");
        }

        List<T> result = ListUtility.skip(source, skipCount);
        result = ListUtility.take(result, takeCount);

        return result;
    }

    /**
     * 取集合中前takeCount个元素
     * @param source 原始集合
     * @param takeCount 取的个数
     */
    public static <T> List<T> take(List<T> source, int takeCount) {
        if (source == null) {
            throw new IllegalArgumentException("source");
        }
        if (takeCount < 0) {
            throw new IllegalArgumentException("takeCount");
        }

        List<T> result = new ArrayList<T>();

        if (takeCount == 0) {
            return result;
        }

        for (T item : source) {
            result.add(item);

            if (result.size() == takeCount) {
                break;
            }
        }

        return result;
    }

    /**
     * 跳过集合前 count个元素
     */
    public static <T> List<T> skip(List<T> list, int count) {
        if (list == null) {
            throw new IllegalArgumentException("source");
        }
        if (count < 0) {
            throw new IllegalArgumentException("takeCount");
        }

        List<T> result = new ArrayList<>();
        for (int i = count; i < list.size(); i ++) {
            result.add(list.get(i));
        }

        return result;
    }
}
